#include "generated.h"
#include <sstream>

using namespace std;
using namespace uhdpbs::db;
using namespace uhdpbs::generated;

namespace uhdpbs {
	namespace menu {
		void generated::edit_row(row* r) {
			int iStartPosition = 1;
			while(true) {
				string sTitle = r->get_table()->get_connection()->get_user_freidnly_name(r->get_table()->get_name()) + " Record";
				string_vector* psvColumns = r->get_table()->get_columns();

				Menu mnu = Menu(sTitle, " > ", "");

				int maxWidth = 0;
				for(int cnt = 0; cnt < psvColumns->size(); cnt++) {
					string sColName = (*psvColumns)[cnt];
					string sNiceName = r->get_table()->get_connection()->get_user_freidnly_name(sColName);
					if(sNiceName.length() > maxWidth)
						maxWidth = sNiceName.length();
				}

				for(int cnt = 0; cnt < psvColumns->size(); cnt++) {		
					string sColName = (*psvColumns)[cnt];
					string sNiceName = r->get_table()->get_connection()->get_user_freidnly_name(sColName);
					string sValue = r->get_value(sColName);

					mnu.AddOption(Pad(sNiceName, maxWidth, true) + ": " + sValue);
				}

				mnu.AddOption("Reset Record to Original Values");
				mnu.AddOption("Delete Record and Return");
				mnu.AddOption("Return to Previous Menu");

				int iSelection = mnu.Play(iStartPosition);
				VP_ClearScreen();
				if(iSelection <= psvColumns->size()) {
					string sColName = (*psvColumns)[iSelection - 1];
					if(sColName == "id") {
						cout << "The ID will be assigned when the record is saved." << endl;
						cout << "Press enter to continue...";
						cin.get();
					}else {
						string sNiceName = r->get_table()->get_connection()->get_user_freidnly_name(sColName);

						cout << sNiceName << ": ";

						string sNewValue = "";
						char pcBuffer[1024];
						cin.getline(pcBuffer, sizeof(pcBuffer));

						r->set_value(sColName, pcBuffer);
					}
				} else if(iSelection == psvColumns->size() + 1) {
					r->reset();
				} else if(iSelection == psvColumns->size() + 2) {
					r->is_deleted(true);
					return;
				} else if(iSelection == psvColumns->size() + 3) {
					return;
				} else {
					cout << "Invalid selection" << endl;
					cout << "Press enter to continue...";
					cin.get();
				}

				iStartPosition = iSelection;
			}
		}

		void generated::appointment_list(appointment_table* tbl) {
			int iStartPosition = 1;
			
			while(true) {
				Menu mnu = Menu("Appointments", " > ", "");
				for(int cnt = 0; cnt < tbl->get_rows()->size(); cnt++) {
					appointment_row r = (appointment_row) (*tbl->get_rows())[cnt];
					patient_table pt = patient_table(tbl->get_connection());
					patient_row pr = pt.create_new_row();
					pr.set_id(r.get_patient_id());
					pt.get_rows()->push_back(pr);
					if(pt.load() != 1) {
						cout << "An appointment is linked to a patient that does not exist.  Please use MySQL to fix." << endl;
						cout << "Press any key to continue...";
						cin.get();
						cin.get();
						return;
					}
					string sPatient = ((patient_row) (*pt.get_rows())[0]).get_last_name();
					practitioner_table doct = practitioner_table(tbl->get_connection());
					practitioner_row docr = pt.create_new_row();
					docr.set_id(r.get_practitioner_id());
					doct.get_rows()->push_back(docr);
					if(doct.load() != 1) {
						cout << "An appointment is linked to a patient that does not exist.  Please use MySQL to fix." << endl;
						cout << "Press any key to continue...";
						cin.get();
						cin.get();
						return;
					}
					string sDoc = ((practitioner_row) (*doct.get_rows())[0]).get_last_name();
					string sDisplay = Pad(r.get_id(), 10) + " " + Pad(r.get_date(), 10) + " " + Pad(r.get_start(), 10) + " " + Pad(sDoc, 10) + " " + Pad(sPatient, 10);
					mnu.AddOption(sDisplay);
				}

				mnu.AddOption("Add New Record");
				mnu.AddOption("Return to Previous Menu");

				int iSelection = mnu.Play(iStartPosition);
				VP_ClearScreen();
				if(iSelection <= tbl->get_rows()->size()) {
					row r = (*tbl->get_rows())[iSelection - 1];
					edit_row(&r);
					(*tbl->get_rows())[iSelection - 1] = r;
					tbl->save();
					if(tbl->get_connection()->get_error().length() > 0) {
						cout << tbl->get_connection()->get_error() << endl;
						cout << "Press enter to continue...";
						cin.get();
						tbl->get_connection()->clear_error();
					}
					tbl->load();
					if(tbl->get_connection()->get_error().length() > 0) {
						cout << tbl->get_connection()->get_error() << endl;
						cout << "Press enter to continue...";
						cin.get();
						tbl->get_connection()->clear_error();
					}
				} else if(iSelection == tbl->get_rows()->size() + 1) {
					row r = tbl->create_new_row();
					edit_row(&r);
					tbl->get_rows()->push_back(r);
					tbl->save();
					if(tbl->get_connection()->get_error().length() > 0) {
						cout << tbl->get_connection()->get_error() << endl;
						cout << "Press enter to continue...";
						cin.get();
						tbl->get_connection()->clear_error();
					}
					tbl->load();
					if(tbl->get_connection()->get_error().length() > 0) {
						cout << tbl->get_connection()->get_error() << endl;
						cout << "Press enter to continue...";
						cin.get();
						tbl->get_connection()->clear_error();
					}
				} else if(iSelection == tbl->get_rows()->size() + 2) {
					return;
				} else {
					cout << "Invalid selection" << endl;
					cout << "Press enter to continue...";
					cin.get();
				}

				iStartPosition = iSelection;
			}
		}
		void generated::patient_list(patient_table* tbl) {
			int iStartPosition = 1;
			while(true) {
				Menu mnu = Menu("Patient List", " > ", "");
				for(int cnt = 0; cnt < tbl->get_rows()->size(); cnt++) {
					patient_row r = (patient_row) (*tbl->get_rows())[cnt];
					string sDisplay = Pad(r.get_id(), 10) + Pad(r.get_last_name() + ", " + r.get_first_name(), 20) + "(" + r.get_dob() + ")";
					mnu.AddOption(sDisplay);
				}
				mnu.AddOption("Add New Record");
				mnu.AddOption("Return to Previous Menu");

				int iSelection = mnu.Play(iStartPosition);
				VP_ClearScreen();
				if(iSelection <= tbl->get_rows()->size()) {
					row r = (*tbl->get_rows())[iSelection - 1];
					edit_row(&r);
					(*tbl->get_rows())[iSelection - 1] = r;
					tbl->save();
					if(tbl->get_connection()->get_error().length() > 0) {
						cout << tbl->get_connection()->get_error() << endl;
						cout << "Press enter to continue...";
						cin.get();
						tbl->get_connection()->clear_error();
					}
					tbl->load();
					if(tbl->get_connection()->get_error().length() > 0) {
						cout << tbl->get_connection()->get_error() << endl;
						cout << "Press enter to continue...";
						cin.get();
						tbl->get_connection()->clear_error();
					}
				} else if(iSelection == tbl->get_rows()->size() + 1) {
					row r = tbl->create_new_row();
					edit_row(&r);
					tbl->get_rows()->push_back(r);
					tbl->save();
					if(tbl->get_connection()->get_error().length() > 0) {
						cout << tbl->get_connection()->get_error() << endl;
						cout << "Press enter to continue...";
						cin.get();
						tbl->get_connection()->clear_error();
					}
					tbl->load();
					if(tbl->get_connection()->get_error().length() > 0) {
						cout << tbl->get_connection()->get_error() << endl;
						cout << "Press enter to continue...";
						cin.get();
						tbl->get_connection()->clear_error();
					}
				} else if(iSelection == tbl->get_rows()->size() + 2) {
					return;
				} else {
					cout << "Invalid selection" << endl;
					cout << "Press enter to continue...";
					cin.get();
				}

				iStartPosition = iSelection;
			}
		}
		void generated::payment_list(payment_table* tbl) {
			int iStartPosition = 1;
			while(true) {
				Menu mnu = Menu("Payment List", " > ", "");
				for(int cnt = 0; cnt < tbl->get_rows()->size(); cnt++) {
					payment_row r = (payment_row) (*tbl->get_rows())[cnt];

					patient_table pt = patient_table(tbl->get_connection());
					patient_row pr = pt.create_new_row();
					pr.set_id(r.get_patient_id());
					pt.get_rows()->push_back(pr);
					if(pt.load() != 1) {
						cout << "An appointment is linked to a patient that does not exist.  Please use MySQL to fix." << endl;
						cout << "Press any key to continue...";
						cin.get();
						cin.get();
						return;
					}
					string sPatient = ((patient_row) (*pt.get_rows())[0]).get_last_name();
					string sDisplay = Pad(r.get_id(), 10) + " " + Pad(r.get_date(), 10) + " " + " " + Pad(sPatient, 10) + "  $"+r.get_amount();
					mnu.AddOption(sDisplay);
				}

				mnu.AddOption("Add New Record");
				mnu.AddOption("Return to Previous Menu");

				int iSelection = mnu.Play(iStartPosition);
				VP_ClearScreen();
				if(iSelection <= tbl->get_rows()->size()) {
					row r = (*tbl->get_rows())[iSelection - 1];
					edit_row(&r);
					(*tbl->get_rows())[iSelection - 1] = r;
					tbl->save();
					if(tbl->get_connection()->get_error().length() > 0) {
						cout << tbl->get_connection()->get_error() << endl;
						cout << "Press enter to continue...";
						cin.get();
						tbl->get_connection()->clear_error();
					}
					tbl->load();
					if(tbl->get_connection()->get_error().length() > 0) {
						cout << tbl->get_connection()->get_error() << endl;
						cout << "Press enter to continue...";
						cin.get();
						tbl->get_connection()->clear_error();
					}
				} else if(iSelection == tbl->get_rows()->size() + 1) {
					row r = tbl->create_new_row();
					edit_row(&r);
					tbl->get_rows()->push_back(r);
					tbl->save();
					if(tbl->get_connection()->get_error().length() > 0) {
						cout << tbl->get_connection()->get_error() << endl;
						cout << "Press enter to continue...";
						cin.get();
						tbl->get_connection()->clear_error();
					}
					tbl->load();
					if(tbl->get_connection()->get_error().length() > 0) {
						cout << tbl->get_connection()->get_error() << endl;
						cout << "Press enter to continue...";
						cin.get();
						tbl->get_connection()->clear_error();
					}
				} else if(iSelection == tbl->get_rows()->size() + 2) {
					return;
				} else {
					cout << "Invalid selection" << endl;
					cout << "Press enter to continue...";
					cin.get();
				}

				iStartPosition = iSelection;
			}
		}
		void generated::practitioner_list(practitioner_table* tbl) {
			int iStartPosition = 1;
			while(true) {
				Menu mnu = Menu("Practitioner List", " > ", "");
				for(int cnt = 0; cnt < tbl->get_rows()->size(); cnt++) {
					practitioner_row r = (practitioner_row) (*tbl->get_rows())[cnt];

					string sDisplay = Pad(r.get_id(), 10) + Pad(r.get_last_name() + ", " + r.get_first_name(), 20) + " (" + r.get_dob() + ")";

					mnu.AddOption(sDisplay);
				}

				mnu.AddOption("Add New Record");
				mnu.AddOption("Return to Previous Menu");

				int iSelection = mnu.Play(iStartPosition);
				VP_ClearScreen();
				if(iSelection <= tbl->get_rows()->size()) {
					row r = (*tbl->get_rows())[iSelection - 1];
					edit_row(&r);
					(*tbl->get_rows())[iSelection - 1] = r;
					tbl->save();
					if(tbl->get_connection()->get_error().length() > 0) {
						cout << tbl->get_connection()->get_error() << endl;
						cout << "Press enter to continue...";
						cin.get();
						tbl->get_connection()->clear_error();
					}
					tbl->load();
					if(tbl->get_connection()->get_error().length() > 0) {
						cout << tbl->get_connection()->get_error() << endl;
						cout << "Press enter to continue...";
						cin.get();
						tbl->get_connection()->clear_error();
					}
				} else if(iSelection == tbl->get_rows()->size() + 1) {
					row r = tbl->create_new_row();
					edit_row(&r);
					tbl->get_rows()->push_back(r);
					tbl->save();
					if(tbl->get_connection()->get_error().length() > 0) {
						cout << tbl->get_connection()->get_error() << endl;
						cout << "Press enter to continue...";
						cin.get();
						tbl->get_connection()->clear_error();
					}
					tbl->load();
					if(tbl->get_connection()->get_error().length() > 0) {
						cout << tbl->get_connection()->get_error() << endl;
						cout << "Press enter to continue...";
						cin.get();
						tbl->get_connection()->clear_error();
					}
				} else if(iSelection == tbl->get_rows()->size() + 2) {
					return;
				} else {
					cout << "Invalid selection" << endl;
					cout << "Press enter to continue...";
					cin.get();
				}

				iStartPosition = iSelection;
			}
		}
		void generated::visit_list(visit_table* tbl) {
			int iStartPosition = 1;

			while(true) {
				Menu mnu = Menu("Visits", " > ", "");
				for(int cnt = 0; cnt < tbl->get_rows()->size(); cnt++) {
					visit_row r = (visit_row) (*tbl->get_rows())[cnt];
					patient_table pt = patient_table(tbl->get_connection());
					patient_row pr = pt.create_new_row();
					pr.set_id(r.get_patient_id());
					pt.get_rows()->push_back(pr);
					if(pt.load() != 1) {
						cout << "An appointment is linked to a patient that does not exist.  Please use MySQL to fix." << endl;
						cout << "Press any key to continue...";
						cin.get();
						cin.get();
						return;
					}
					string sPatient = ((patient_row) (*pt.get_rows())[0]).get_last_name();
					practitioner_table doct = practitioner_table(tbl->get_connection());
					practitioner_row docr = pt.create_new_row();
					docr.set_id(r.get_practitioner_id());
					doct.get_rows()->push_back(docr);
					if(doct.load() != 1) {
						cout << "An appointment is linked to a patient that does not exist.  Please use MySQL to fix." << endl;
						cout << "Press any key to continue...";
						cin.get();
						cin.get();
						return;
					}
					string sDoc = ((practitioner_row) (*doct.get_rows())[0]).get_last_name();
					string sDisplay = Pad(r.get_id(), 10) + " " + Pad(r.get_date(), 10) + " " + Pad(sDoc, 10) + " " + Pad(sPatient, 10) + r.get_price();
					mnu.AddOption(sDisplay);
				}

				mnu.AddOption("Add New Record");
				mnu.AddOption("Return to Previous Menu");

				int iSelection = mnu.Play(iStartPosition);
				VP_ClearScreen();
				if(iSelection <= tbl->get_rows()->size()) {
					row r = (*tbl->get_rows())[iSelection - 1];
					edit_row(&r);
					(*tbl->get_rows())[iSelection - 1] = r;
					tbl->save();
					if(tbl->get_connection()->get_error().length() > 0) {
						cout << tbl->get_connection()->get_error() << endl;
						cout << "Press enter to continue...";
						cin.get();
						tbl->get_connection()->clear_error();
					}
					tbl->load();
					if(tbl->get_connection()->get_error().length() > 0) {
						cout << tbl->get_connection()->get_error() << endl;
						cout << "Press enter to continue...";
						cin.get();
						tbl->get_connection()->clear_error();
					}
				} else if(iSelection == tbl->get_rows()->size() + 1) {
					row r = tbl->create_new_row();
					edit_row(&r);
					tbl->get_rows()->push_back(r);
					tbl->save();
					if(tbl->get_connection()->get_error().length() > 0) {
						cout << tbl->get_connection()->get_error() << endl;
						cout << "Press enter to continue...";
						cin.get();
						tbl->get_connection()->clear_error();
					}
					tbl->load();
					if(tbl->get_connection()->get_error().length() > 0) {
						cout << tbl->get_connection()->get_error() << endl;
						cout << "Press enter to continue...";
						cin.get();
						tbl->get_connection()->clear_error();
					}
				} else if(iSelection == tbl->get_rows()->size() + 2) {
					return;
				} else {
					cout << "Invalid selection" << endl;
					cout << "Press enter to continue...";
					cin.get();
				}

				iStartPosition = iSelection;
			}
		}

		string generated::Pad(string val, int wide, bool dLeftPad) {
			int iCharsNeeded = wide - val.length();
			string ret = "";
			if(iCharsNeeded <= 0) {
				// val is longer than column, truncate
				for(int cnt = 0; cnt < wide; cnt++)
					ret += val[cnt];
			} else {
				// needs white added infront
				if(!dLeftPad)
					ret += val;
					
				for(int cnt = 0; cnt < iCharsNeeded; cnt++)
					ret += " ";
					
				if(dLeftPad)
					ret += val;
			}

			return ret;
		}
		string generated::Pad(float val, int wide, bool dLeftPad) {
			stringstream ssout = stringstream(ios::out);
			ssout << val;
			return Pad(ssout.str(), wide, dLeftPad);
		}


	}
}
	